package com.delos.rbac.aspect;

import com.delos.rbac.annotation.IgnoreAuthentication;
import com.delos.rbac.error.ExceptionEnum;
import com.delos.rbac.error.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * 授权配置验证
 *
 * @author zouyaowen
 * @date 2020-07-27
 */
@Aspect
@Slf4j
@Configuration
public class AuthenticationAspect {

    private static final String authentication = "Authentication";

    @Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
    public void getMapping() {
    }

    @Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
    public void postMapping() {
    }

    @Pointcut("@annotation(org.springframework.web.bind.annotation.PutMapping)")
    public void putMapping() {
    }

    @Pointcut("@annotation(org.springframework.web.bind.annotation.DeleteMapping)")
    public void deleteMapping() {
    }

    /**
     * 授权验证处理
     *
     * @param joinPoint 连接点
     */
    @Before("getMapping() || postMapping() || putMapping() || deleteMapping()")
    public void doBefore(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        Class<?> clazz = signature.getDeclaringType();
        if (clazz.isAnnotationPresent(IgnoreAuthentication.class)) {
            return;
        }
        MethodSignature methodSignature = (MethodSignature) signature;
        Method targetMethod = methodSignature.getMethod();
        if (targetMethod.isAnnotationPresent(IgnoreAuthentication.class)) {
            return;
        }
        // 获取当前http请求
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 获取头信息
        String authorization = request.getHeader(authentication);
        String remoteAddr = request.getRemoteAddr();
        String requestURI = request.getRequestURI();
        if (StringUtils.isEmpty(authorization)) {
            log.error("授权信息缺失,url={},remoteAddr={}", requestURI, remoteAddr);
            throw new ServiceException(ExceptionEnum.INTERNAL_ERROR);
        } else {
            //验证授权信息
            //TODO
            // 1 、根据Token获取用户信息
            // 2 、校验角色
            // 3 、判断权限是否通过进而确认是否放行
            // 4 、RequestHolder.setUserInfo();
        }
    }
}
